﻿#include "CardGame.h"
#include <ctime>


CardGame::CardGame()
{
	selfCards_node = Node::create();
}
//将0-53的值，转变为对应的某张牌的精灵
Sprite *CardGame::getCardSpriteWithValue(int value)
{
	string file_name = "";

	if (value == 52) {
		// 小王
		file_name = "xiaowang.png";
	}
	else if (value == 53) {
		// 大王
		file_name = "dawang.png";
	}
	else {
		// 如何得到花色？
		int flower = value / 13 + 1;
		// 牌的值？
		int _value = value % 13 + 1;
		switch (flower) {
		case 1: // ♠️
			file_name = StringUtils::format("hei-%d.png", _value);
			break;
		case 2: // ♦️
			file_name = StringUtils::format("fk-%d.png", _value);
			break;
		case 3: // ♣️
			file_name = StringUtils::format("mh-%d.png", _value);
			break;
		case 4: // ♥️
			file_name = StringUtils::format("hong-%d.png", _value);
			break;
		default:
			break;
		}
	}

	Sprite *cardSprite = Sprite::createWithSpriteFrameName(file_name);
	cardSprite->setTag(value);//有助于从父节点通过tag值找到对应的牌的精灵
	return cardSprite;
}
bool hasKing(vector<int> arr)
{
	for (int i = 0; i < arr.size(); i++)
	{
		if (arr[0] >= 52 || arr[1] >= 52) {
			return true;
		}
	}
	return false;
}
//判断是否为王炸
bool isKingBomb(vector<int> arr) {
	if (arr[0] >= 52 && arr[1] >= 52) {
		return true;
	}
	else
	{
		return false;
	}
}
//判断是否为红十炸弹
bool isRedTenBomb(vector<int> arr) {
	if ((arr[0] == 22 && arr[1] == 48) || (arr[0] == 48 && arr[1] == 22)) {
		return true;
	}
	else {
		return false;
	}
}
//判断是否为对子
bool isDouble(vector<int> arr) {
	if (hasKing(arr)) {
		return false;
	}
	else if (arr[0] % 13 == arr[1] % 13) {
		return true;
	}
	else {
		return false;
	}
}
//判断是否为三张或者四张的炸弹
bool isThreeOrFourBomb(vector<int> arr)
{
	//排除大小王的干扰
	if (hasKing(arr)) {
		return false;
	}

	bool allSame = true;
	for (int i = 1; i < arr.size(); i++)
	{
		//如果有一张牌不相等，就跳出结束
		if (arr[0]%13 != arr[i]%13) {
			allSame = false;
			break;
		}
	}
	if (allSame) {
		return true;
	}
	else {
		return false;
	}
}
//判断是否为顺子
bool isStraight(vector<int> arr)
{
	if (hasKing(arr)) {
		return false;
	}
	// A 2 3 4 5 6 7 8 9 10 J  Q   K   *
	// 0 1 2 3 4 5 6 7 8 9 10  11  12  13   下标
	// 0 0 0 0 0 0 0 0 0 0  0  0   0   0	次数
	vector<int> vec(14, 0);//用vector记录每个点数的牌出现的次数
	for (int i = 0; i < arr.size(); i++)
	{
		vec[arr[i] % 13] += 1;
	}
	//如何判断既有K又有A
	if (vec[12] > 0 && vec[0] > 0) {
		vec[0]--;
		vec[13]++;
	}
	//计算vec里连续的1出现的次数,只要出现1，后面没出现1就中断
	int count = 0;//记录连续1的次数
	for (int i = 0; i < vec.size(); i++)
	{
		if (vec[i] == 1) {
			count++;
		}
		//连续的1发生中断
		else if (count != 0) {
			break;
		}
	}
	if (count == arr.size()) {
		return true;
	}
	else {
		return false;
	}
}
PokerType CardGame::getPokerTypeWithCards(vector<int> arr)
{
	//log("%d", PokerType::POKER_TYPE_ERROR);
	//选择的牌数
	int len = (int)arr.size();
	if (len == 1) {
		return PokerType::POKER_TYPE_SINGLE;
	}
	else if (len == 2) {
		if (isKingBomb(arr)) {
			return PokerType::POKER_TYPE_KING_BOMB;
		}
		else if (isRedTenBomb(arr)) {
			return PokerType::POKER_TYPE_REDTEN_BOMB;
		}
		else if (isDouble(arr)) {
			return PokerType::POKER_TYPE_DOUBLE;
		}
	}
	else if (len == 3 || len == 4) {
		//判断是否为炸弹
		if (isThreeOrFourBomb) {
			if (len == 3) {
				return PokerType::POKER_TYPE_THREE_BOMB;
			}
			else if(len == 4){
				return PokerType::POKER_TYPE_FOUR_BOMB;
			}
		}
		else if(isStraight(arr)) {
			return PokerType::POKER_TYPE_STRAIGHT;
		}
	}
	else if (len > 4) {
		return PokerType::POKER_TYPE_STRAIGHT;
	}
	return PokerType::POKER_TYPE_ERROR;
}
//tag:0~53中的某个值
int getValue(int tag) {
	int res = tag % 13 + 1;
	//3~K:3~13
	//A
	if (res == 1) res = 14;
	//2
	if (res == 2) res = 15;
	//小王
	if (tag == 52) res = 16;
	//大王
	if (tag == 53) res = 17;
	//红十
	if (tag == 22||tag == 48) res = 18;

	return res;
}
//获取手牌里能压的炸弹	3张<4张<王炸<红十
vector<int> getBomb(int selfCards[], int selfCardsCount, vector<int> lastCards) {
	
	vector<int> table(15,0);
	//遍历计数
	for (int i = 0; i < selfCardsCount; i++)
	{
		//王
		if (selfCards[i] == 52 || selfCards[i] == 53) {
			table[13]++;
		}
		//红十
		if (selfCards[i] == 22 || selfCards[i] == 48) {
			table[7]++;
			table[14]++;
		}
		else {
			table[getValue(selfCards[i]) - 3]++;
		}
	}
	for (int i = 0; i < 15; i++)
	{
		log("%d", table[i]);
	}
	vector<int> result;
	//1.寻找最小的3张炸弹   3~K:0~12
	for (int i = 0; i <= 12; i++)
	{
		if (table[i] == 3) {
			for (int j = selfCardsCount-1; j >= 0; j--)
			{
				if (getValue(selfCards[j]) - 3 == i ) {
					result.push_back(selfCards[j]);
					if (result.size() == 3) {
						break;
					}
				}
			}
			break;
		}
	}
	//3张炸弹是有红十组成的情况
	if (result.size() != 3 && result.size() > 0) {
		//
		for (int i = selfCardsCount-1; i >= 0; i--)
		{
			if (selfCards[i] == 22 || selfCards[i] == 48) {
				result.push_back(selfCards[i]);
				if (result.size() == 3) {
					break;
				}
			}
		}
	}
	return result;
	
	//2.上面没找到，则寻找最小的4张炸弹
	for (int i = 0; i <= 12; i++)
	{
		if (table[i] == 4) {
			for (int j = 0; j < selfCardsCount; j++)
			{
				if (getValue(selfCards[j]) - 3 == i) {
					result.push_back(selfCards[j]);
				}
			}
			break;
		}
	}
	//4张炸弹是有红十组成的情况
	if (result.size() != 4 && result.size() > 0) {
		for (int i = selfCardsCount-1; i >= 0; i--)
		{
			if (selfCards[i] == 22 || selfCards[i] == 48) {
				result.push_back(selfCards[i]);
				if (result.size() == 4) {
					break;
				}
			}
		}
	}
	return result;
	//3.上面没找到，寻找是否有王炸
	if (table[13] == 2) {
		result.push_back(52);
		result.push_back(53);
		return result;
	}
	//4.上面没找到，寻找是否有双红十
	if (table[14] == 2) {
		result.push_back(22);
		result.push_back(48);
		return result;
	}
	//5.都没有，就没有了
}
vector<int> CardGame::suggest(int selfCards[], int selfCardsCount, vector<int> lastCards)
{
	vector<int> vec;
	//获取上家玩家所出牌的类型
	PokerType lastType = getPokerTypeWithCards(lastCards);
	//是否为单牌
	if (lastType == POKER_TYPE_SINGLE) {
		//判断是否有更大的单牌，有的话获取
		for (int i = selfCardsCount-1; i >= 0; i--)
		{
			//找到
			if (getValue(selfCards[i]) > getValue(lastCards[0])) {
				vec.push_back(selfCards[i]);
				break;
			}
			//判断没有找到更大的单牌
			if (vec.size() == 0) {
				//寻找手牌里最小的炸弹
				return getBomb(selfCards, selfCardsCount, lastCards);
			}
		}
	}
	else if (lastType == POKER_TYPE_DOUBLE) {
		//寻找更大的对子（注意红10+黑10的对子）
		for (int i = selfCardsCount-1; i > 0; i--)
		{
			int left = getValue(selfCards[i - 1]);
			int right = getValue(selfCards[i]);
			//判断我只有一张黑10
			if (left != 10 && right == 10) {
				//先判断10组成的对子能不能压过上家的对子
				if (right > getValue(lastCards[0])) {
					//寻找一张红10来匹配
					for (int j = selfCardsCount-1; j >= 0; j--)
					{
						if (selfCards[j] == 22 || selfCards[j] == 48) {
							vec.push_back(selfCards[i]);
							vec.push_back(selfCards[j]);
							return vec;
						}
					}
					//判断没有找到更大的单牌
					if (vec.size() == 0) {
						//寻找手牌里最小的炸弹
						return getBomb(selfCards, selfCardsCount, lastCards);
					}
				}
			}
			else if (left == right &&right > getValue(lastCards[0])&&right!=18) {
				vec.push_back(selfCards[i]);
				vec.push_back(selfCards[i-1]);
				return vec;
			}
		}
	}
	return vec;
}

static CardGame *s_SharedGame = nullptr;
CardGame * CardGame::getInstance()
{
	if (!s_SharedGame) {
		s_SharedGame = new(std::nothrow)CardGame;
		CCASSERT(s_SharedGame, "FATAL:");
	}
	return s_SharedGame;
}
//清除单例对象
void CardGame::cleanInstance()
{
	CC_SAFE_DELETE(s_SharedGame);
}

void CardGame::shuffle(int a[], int len) {
	int index, temple, i;
	for (i = 0; i < 54; i++) {
		a[i] = i;
	}
	srand((unsigned)time(NULL));
	for (i = len - 1; i > 0; i--) {
		index = rand() % i;
		// 交换i索引和index索引里储存的值
		temple = a[i];
		a[i] = a[index];
		a[index] = temple;
	}
	// 打印下洗好牌后的情况
	for (i = 0; i < len; i++) {
		CCLOG("%d ", a[i]);
	}
}